﻿namespace eeenno.SpeeedReaderUI.NativeWebBrowser.Runtime.InteropServices
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;

    public abstract class AdvancedMarshaler
    {
        private BinaryReader binReader;
        private BinaryWriter binWriter;
        protected byte[] data;
        private int size;
        private MemoryStream stream;

        public AdvancedMarshaler()
        {
            this.size = this.GetSize();
            this.data = new byte[this.size];
        }

        private static bool CompareByteArrays(byte[] data1, byte[] data2)
        {
            if ((data1 != null) || (data2 != null))
            {
                if ((data1 == null) || (data2 == null))
                {
                    return false;
                }
                if (data1.Length != data2.Length)
                {
                    return false;
                }
                for (int i = 0; i < data1.Length; i++)
                {
                    if (data1[i] != data2[i])
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        public void Deserialize()
        {
            if (this.data != null)
            {
                if (this.binReader != null)
                {
                    this.binReader.Close();
                    this.stream.Close();
                }
                this.stream = new MemoryStream(this.data);
                this.binReader = new BinaryReader(this.stream, Encoding.Unicode);
                this.ReadFromStream(this.binReader);
                this.binReader.Close();
            }
        }

        public void DeserializeFromByteArray(byte[] b)
        {
            int length = (b.Length < this.data.Length) ? b.Length : this.data.Length;
            Array.Copy(b, 0, this.data, 0, length);
            this.Deserialize();
        }

        protected int GetFieldSize(FieldInfo field)
        {
            int num = 0;
            CustomMarshalAsAttribute attribute = (CustomMarshalAsAttribute) field.GetCustomAttributes(typeof(CustomMarshalAsAttribute), true)[0];
            if (attribute == null)
            {
                return num;
            }
            if (attribute.SizeField != null)
            {
                return (int) base.GetType().GetField(attribute.SizeField).GetValue(this);
            }
            return attribute.SizeConst;
        }

        public int GetSize()
        {
            int num = 0;
            foreach (FieldInfo info in base.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                if (info.FieldType.IsArray)
                {
                    num += this.GetFieldSize(info);
                }
                else if (info.FieldType == typeof(string))
                {
                    num += this.GetFieldSize(info) * 2;
                }
                else if (info.FieldType.IsPrimitive)
                {
                    num += Marshal.SizeOf(info.FieldType);
                }
                else
                {
                    AdvancedMarshaler marshaler = (AdvancedMarshaler) Activator.CreateInstance(info.FieldType);
                    num += marshaler.GetSize();
                }
            }
            return num;
        }

        public virtual void ReadFromStream(BinaryReader reader)
        {
            object[] parameters = null;
            foreach (FieldInfo info in base.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                MethodInfo info2 = (MethodInfo) MarshallingMethods.ReadMethods[info.FieldType];
                if (info.FieldType.IsArray)
                {
                    Type elementType = info.FieldType.GetElementType();
                    if (elementType.IsValueType && elementType.IsPrimitive)
                    {
                        if ((elementType == typeof(char)) || (elementType == typeof(byte)))
                        {
                            parameters = new object[] { this.GetFieldSize(info) };
                            info.SetValue(this, info2.Invoke(reader, parameters));
                        }
                        else
                        {
                            parameters = new object[2];
                            parameters[0] = reader;
                            int num = 1;
                            if (elementType == typeof(int))
                            {
                                num = 4;
                            }
                            parameters[1] = this.GetFieldSize(info) / num;
                            info.SetValue(this, info2.Invoke(null, parameters));
                        }
                    }
                    else
                    {
                        int fieldSize = this.GetFieldSize(info);
                        info2 = (MethodInfo) MarshallingMethods.ReadMethods[typeof(AdvancedMarshaler)];
                        Array array = Array.CreateInstance(elementType, fieldSize);
                        for (int i = 0; i < fieldSize; i++)
                        {
                            array.SetValue(Activator.CreateInstance(elementType), i);
                            info2.Invoke(array.GetValue(i), new object[] { reader });
                        }
                        info.SetValue(this, array);
                    }
                }
                else if (info.FieldType == typeof(string))
                {
                    parameters = new object[] { reader, this.GetFieldSize(info) };
                    info.SetValue(this, info2.Invoke(null, parameters));
                }
                else if (info.FieldType.IsValueType && info.FieldType.IsPrimitive)
                {
                    info.SetValue(this, info2.Invoke(reader, null));
                }
                else
                {
                    ((AdvancedMarshaler) info.GetValue(this)).ReadFromStream(reader);
                }
            }
        }

        public void Serialize()
        {
            if (this.data != null)
            {
                this.stream = new MemoryStream(this.data);
                this.binWriter = new BinaryWriter(this.stream, Encoding.Unicode);
                this.WriteToStream(this.binWriter);
                this.binWriter.Close();
            }
        }

        public virtual void WriteToStream(BinaryWriter writer)
        {
            object[] parameters = null;
            foreach (FieldInfo info in base.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                object obj2 = info.GetValue(this);
                MethodInfo info2 = (MethodInfo) MarshallingMethods.WriteMethods[info.FieldType];
                if (info.FieldType.IsArray)
                {
                    Type elementType = info.FieldType.GetElementType();
                    if (elementType.IsValueType && elementType.IsPrimitive)
                    {
                        Array array = (Array) info.GetValue(this);
                        parameters = new object[] { writer, array };
                        info2.Invoke(null, parameters);
                    }
                    else
                    {
                        int fieldSize = this.GetFieldSize(info);
                        info2 = (MethodInfo) MarshallingMethods.WriteMethods[typeof(AdvancedMarshaler)];
                        Array array2 = (Array) info.GetValue(this);
                        for (int i = 0; i < fieldSize; i++)
                        {
                            info2.Invoke(array2.GetValue(i), new object[] { writer });
                        }
                    }
                }
                else if (info.FieldType == typeof(string))
                {
                    parameters = new object[] { writer, info.GetValue(this), this.GetFieldSize(info) };
                    info2.Invoke(null, parameters);
                }
                else if (info.FieldType.IsValueType && info.FieldType.IsPrimitive)
                {
                    info2.Invoke(writer, new object[] { obj2 });
                }
                else
                {
                    ((AdvancedMarshaler) obj2).WriteToStream(writer);
                }
            }
        }

        public byte[] ByteArray
        {
            get
            {
                return this.data;
            }
        }

        public int Size
        {
            get
            {
                return this.size;
            }
        }
    }
}

